home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / ted5.zip / IGRABSRC.ZIP / JHUFF.BAK < prev    next >
Text File  |  1993-02-04  |  8KB  |  426 lines

  1. /**************************************************************
  2.     JHUFF.C -- A rle/huffman Data Compression Program
  3. **************************************************************/
  4.  
  5. #include "igrab.h"
  6. #pragma hdrstop
  7.  
  8. unsigned char huge *infile,
  9.           huge *outfile;
  10.  
  11. long inlength,outlength;
  12.  
  13. long counts[256];
  14.  
  15. unsigned huffbits[256];
  16. unsigned long huffstring[256];
  17.  
  18. huffnode nodearray[256];    // 256 nodes is worst case
  19.  
  20. /*
  21. =============================================================================
  22.  
  23.                COMPRESSION SUBS
  24.  
  25. =============================================================================
  26. */
  27.  
  28.  
  29.  
  30. /*
  31. ======================
  32. =
  33. = CountBytes
  34. =
  35. = Adds the bytes in the pointed to area to the counts array
  36. = If this is the first segment, make sure counts is zerod
  37. =
  38. ======================
  39. */
  40.  
  41. void CountBytes (unsigned char huge *start, long length)
  42. {
  43.   long i;
  44.  
  45.   while (length--)
  46.     counts[*start++]++;
  47. }
  48.  
  49. /*
  50. =======================
  51. =
  52. = FindLeast
  53. =
  54. = Returns the byte with the lowest counts value
  55. =
  56. =======================
  57. */
  58.  
  59. int FindLeast (void)
  60. {
  61.   int i,least;
  62.   long low = 0x7fffffff;
  63.  
  64.   for (i=0;i<256;i++)
  65.     if (counts[i]<low)
  66.     {
  67.       low = counts[i];
  68.       least = i;
  69.     }
  70.  
  71.   return least;
  72. }
  73.  
  74. /*========================================================================*/
  75.  
  76. /*
  77. ==================
  78. =
  79. = TraceNode
  80. =
  81. = A recursive function that follows all leaves of nodearray and fills in
  82. = coding tables huffbits and huffstring.
  83. =
  84. ==================
  85. */
  86.  
  87. void TraceNode (int nodenum,int numbits,unsigned long bitstring)
  88. {
  89.   unsigned bit0,bit1;
  90.  
  91.   bit0 = nodearray[nodenum].bit0;
  92.   bit1 = nodearray[nodenum].bit1;
  93.  
  94.   numbits++;
  95.  
  96.  
  97.   if (bit0 <256)
  98.   {
  99.     huffbits[bit0]=numbits;
  100.     huffstring[bit0]=bitstring;        // just added a zero in front
  101.   }
  102.   else
  103.   {
  104.     if (numbits<24)            // if the string is this long, its 0
  105.       TraceNode (bit0-256,numbits,bitstring);
  106.   }
  107.  
  108.   if (bit1 <256)
  109.   {
  110.     huffbits[bit1]=numbits;
  111.     huffstring[bit1]=bitstring+ (1ul<<(numbits-1));    // add a one in front
  112.     if (huffbits[bit1]>24 && counts[bit1])
  113.     {
  114.       puts("Error: Huffman bit string went over 32 bits!");
  115.       exit(1);
  116.     }
  117.   }
  118.   else
  119.   {
  120.     if (numbits<24)            // if the string is this long, its 0
  121.      TraceNode (bit1-256,numbits,bitstring+(1ul<<(numbits-1)));
  122.   }
  123. }
  124.  
  125.  
  126. /*
  127. =======================
  128. =
  129. = Huffmanize
  130. =
  131. = Takes the counts array and builds a huffman tree at
  132. = nodearray, then builds a codeing table.
  133. =======================
  134. */
  135.  
  136. void Huffmanize (void)
  137. {
  138. //
  139. // codes are either bytes if <256 or nodearray numbers+256 if >=256
  140. //
  141.   unsigned value[256],code0,code1;
  142. //
  143. // probablilities are the number of times the code is hit or $ffffffff if
  144. // it is allready part of a higher node
  145. //
  146.   unsigned long prob[256],low,workprob;
  147.  
  148.   int i,worknode,bitlength;
  149.   unsigned long bitstring;
  150.  
  151.   memset(huffstring,0,sizeof(huffstring));
  152.   memset(huffbits,0,sizeof(huffbits));
  153.  
  154. //
  155. // all possible leaves start out as bytes
  156. //
  157.   for (i=0;i<256;i++)
  158.   {
  159.     value[i]=i;
  160.     prob[i]=counts[i];
  161.   }
  162.  
  163. //
  164. // start selecting the lowest probable leaves for the ends of the tree
  165. //
  166.  
  167.   worknode = 0;
  168.   while (1)    // break out of when all codes have been used
  169.   {
  170.     //
  171.     // find the two lowest probability codes
  172.     //
  173.  
  174.     code0=0xffff;
  175.     low = 0x7ffffffff;
  176.     for (i=0;i<256;i++)
  177.       if (prob[i]<low)
  178.       {
  179.     code0 = i;
  180.     low = prob[i];
  181.       }
  182.  
  183.     code1=0xffff;
  184.     low = 0x7fffffff;
  185.     for (i=0;i<256;i++)
  186.       if (prob[i]<low && i != code0)
  187.       {
  188.     code1 = i;
  189.     low = prob[i];
  190.       }
  191.  
  192.     if (code1 == 0xffff)
  193.     {
  194.       if (value[code0]<256)
  195.     errout("Weirdo huffman error: last code wasn't a node!");
  196.       if (value[code0]-256 != 254)
  197.     errout("Weirdo huffman error: headnode wasn't 254!");
  198.       break;
  199.     }
  200.  
  201.     //
  202.     // make code0 into a pointer to work
  203.     // remove code1 (make 0xffffffff prob)
  204.     //
  205.     nodearray[worknode].bit0 = value[code0];
  206.     nodearray[worknode].bit1 = value[code1];
  207.  
  208.     value[code0] = 256 + worknode;
  209.     prob[code0] += prob[code1];
  210.     prob[code1] = 0xffffffff;
  211.     worknode++;
  212.   }
  213.  
  214. //
  215. // done with tree, now build table recursively
  216. //
  217.  
  218.   TraceNode (254,0,0);
  219.  
  220. }
  221.  
  222. /*========================================================================*/
  223.  
  224. /*
  225. ===============
  226. =
  227. = OptimizeNodes
  228. =
  229. = Goes through a huffman table and changes the 256-511 node numbers to the
  230. = actular address of the node.  Must be called before HuffExpand
  231. =
  232. ===============
  233. */
  234.  
  235. void OptimizeNodes (huffnode *table)
  236. {
  237.   huffnode *node;
  238.   int i;
  239.  
  240.   node = table;
  241.  
  242.   for (i=0;i<255;i++)
  243.   {
  244.     if (node->bit0 >= 256)
  245.       node->bit0 = (unsigned)(table+(node->bit0-256));
  246.     if (node->bit1 >= 256)
  247.       node->bit1 = (unsigned)(table+(node->bit1-256));
  248.     node++;
  249.   }
  250. }
  251.  
  252. /*========================================================================*/
  253.  
  254. /*
  255. ======================
  256. =
  257. = HuffCompress
  258. =
  259. = The file must be counted with CountBytes and then Huffmanized first
  260. =
  261. ======================
  262. */
  263.  
  264. #if 0
  265. long HuffCompress (unsigned char huge *source, long length,
  266.   unsigned char huge *dest)
  267. {
  268.   long outlength;
  269.   unsigned long string;
  270.   unsigned biton,bits;
  271.   unsigned char byte;
  272.  
  273.   outlength = biton = 0;
  274.  
  275.   *(long huge *)dest=0;        // so bits can be or'd on
  276.  
  277.   while (length--)
  278.   {
  279.     byte = *source++;
  280.     bits = huffbits[byte];
  281.     string = huffstring[byte] << biton;
  282.     *(long huge *)(dest+1)=0;    // so bits can be or'd on
  283.     *(long huge *)dest |= string;
  284.     biton += bits;        // advance this many bits
  285.     dest+= biton/8;
  286.     biton&=7;            // stay under 8 shifts
  287.     outlength+=bits;
  288.   }
  289.  
  290.   return (outlength+7)/8;
  291. }
  292. #endif
  293.  
  294. /*========================================================================*/
  295.  
  296. /*
  297. ======================
  298. =
  299. = HuffExpand
  300. =
  301. ======================
  302. */
  303.  
  304. void HuffExpand (unsigned char huge *source, unsigned char huge *dest,
  305.   long length,huffnode *hufftable)
  306. {
  307.   unsigned bit,byte,node,code;
  308.   unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;
  309.   huffnode *nodeon,*headptr;
  310.  
  311.   nodeon = headptr = hufftable+254;    // head node is allways node 254
  312.  
  313.   bit = 1;
  314.   byte = *source++;
  315.  
  316.   while (length)
  317.   {
  318.     if (byte&bit)
  319.       code = nodeon->bit1;
  320.     else
  321.       code = nodeon->bit0;
  322.  
  323.     bit<<=1;
  324.     if (bit==256)
  325.     {
  326.       bit=1;
  327.       byte = *source++;
  328.     }
  329.  
  330.     if (code<256)
  331.     {
  332.       *dest++=code;
  333.       nodeon=headptr;
  334.       length--;
  335.     }
  336.     else
  337.       nodeon = (huffnode *)code;
  338.   }
  339.  
  340.  
  341. #if 0
  342.  
  343.   source++;    // normalize
  344.   source--;
  345.   dest++;
  346.   dest--;
  347.  
  348.   sourceseg = FP_SEG(source);
  349.   sourceoff = FP_OFF(source);
  350.   destseg = FP_SEG(dest);
  351.   destoff = FP_OFF(dest);
  352.  
  353.   length--;
  354. //
  355. // al = source byte
  356. // cl = bit in source (1,2,4,8,...)
  357. // dx = code
  358. //
  359. // ds:si source
  360. // es:di dest
  361. // ss:bx node pointer
  362. //
  363.  
  364. asm     mov    bx,headptr
  365. asm    mov    cl,1
  366.  
  367. asm    mov    si,sourceoff
  368. asm    mov    di,destoff
  369. asm    mov    es,destseg
  370. asm    mov    ds,sourceseg
  371.  
  372. asm    lodsb            // load first byte
  373.  
  374. expand:
  375. asm    test    al,cl        // bit set?
  376. asm    jnz    bit1
  377. asm    mov    dx,ss:bx    // take bit0 path from node
  378. asm    jmp    gotcode
  379. bit1:
  380. asm    mov    dx,ss:bx+2    // take bit1 path
  381.  
  382. gotcode:
  383. asm    shl    cl,1        // advance to next bit position
  384. asm    jnc    sourceup
  385. asm    lodsb
  386. asm    cmp    si,0x10        // normalize ds:si
  387. asm      jb    sinorm
  388. asm    mov    cx,ds
  389. asm    inc    cx
  390. asm    mov    ds,cx
  391. asm    xor    si,si
  392. sinorm:
  393. asm    mov    cl,1        // back to first bit
  394.  
  395. sourceup:
  396. asm    or    dh,dh        // if dx<256 its a byte, else move node
  397. asm    jz    storebyte
  398. asm    mov    bx,dx        // next node = (huffnode *)code
  399. asm    jmp    expand
  400.  
  401. storebyte:
  402. asm    mov    [es:di],dl
  403. asm    inc    di        // write a decopmpressed byte out
  404. asm    mov    bx,headptr    // back to the head node for next bit
  405.  
  406. asm    cmp    di,0x10        // normalize es:di
  407. asm      jb    dinorm
  408. asm    mov    dx,es
  409. asm    inc    dx
  410. asm    mov    es,dx
  411. asm    xor    di,di
  412. dinorm:
  413.  
  414. asm    sub    WORD PTR ss:length,1
  415. asm    jnc    expand
  416. asm      dec    WORD PTR ss:length+2
  417. asm    jns    expand        // when length = ffff ffff, done
  418.  
  419. asm    mov    ax,ss
  420. asm    mov    ds,ax
  421.  
  422. #endif
  423.  
  424. }
  425.